﻿using System;
using System.Text;

namespace CaoNiMaCoolPad
{
    class Message
    {
        /// <summary>
        /// 
        /// </summary>
        public const int MaxMessageLength = 1624;


        readonly static byte[] startFlag = { 0xff, 00, 00, 00 };
        readonly static byte[] receiveBox = { 01, 00, 00, 00, 01, 00, 00, 00, 00, 00, 00, 00 };//01应该是保存发送的。
        readonly static byte[] sentBox = { 07, 00, 00, 00, 04, 00, 00, 00, 00, 00, 00, 00 };//04应该是保存收到的。
        readonly static byte[] darftBox = { 08, 00, 00, 00, 06, 00, 00, 00, 00, 00, 00, 00 };

        const int timeFieldLength = 32;
        const int phoneNumberFieldLength = 68;
        const int nameFieldLength = 82;
        const int contentFieldLength = 1343;

        private readonly Folders m_Folders;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="folders"></param>
        /// <exception cref="FormatException">不可识别的短信开始标记</exception>
        public Message(int sn, byte[] bytes, Folders folders)
        {
            int position = 0;
            if (Match(bytes, position, startFlag) == false)
                SetException(new FormatException("第" + sn + "条短信，不可识别的短信开始标记：" + Program.ByteArrayToString(bytes, position, startFlag.Length)));

            m_Folders = folders;

            position += startFlag.Length;
            try { SetLocation(bytes, position); }
            catch (Exception e) { SetException(e); }

            position += receiveBox.Length;


            try { Time = GetTime(bytes, position); }
            catch (ArgumentException e)
            {
                SetException(new ArgumentException(
                    "第" + sn + "条短信，获取短信日期时发生异常。二进制数据为：" + Program.PhraseUnicode(bytes, position, timeFieldLength), e));
            }
            position += timeFieldLength;

            try { Time2 = GetTime(bytes, position); }
            catch (ArgumentException e)
            {
                SetException(new ArgumentException(
                    "第" + sn + "条短信，获取短信日期时发生异常。二进制数据为：" + Program.PhraseUnicode(bytes, position, timeFieldLength), e));
            }
            position += timeFieldLength;

            PhoneNumber = Program.PhraseUnicode(bytes, position, phoneNumberFieldLength);
            position += phoneNumberFieldLength;

            Name = Program.PhraseUnicode(bytes, position, nameFieldLength);
            position += nameFieldLength;

            Content = Program.PhraseUnicode(bytes, position, contentFieldLength);
        }

        public string Location { get; private set; }
        public string Content { get; private set; }
        public string PhoneNumber { get; private set; }
        public string Name { get; private set; }
        public DateTime Time { get; private set; }
        public DateTime Time2 { get; private set; }
        public Exception Exception { get; private set; }


        private void SetLocation(byte[] message, int position)
        {
            if (Match(message, position, receiveBox))
                Location = "收件箱";
            else if (Match(message, position, sentBox))
                Location = "已发送";
            else if (Match(message, position, darftBox))
                Location = "草稿箱";
            else
            {
                byte b = message[position + 4];
                if (b == 1)
                    Location = "收到短信";
                else if (b == 4)
                    Location = "发出短信";
                else if (b == 6)
                    Location = "草稿箱";

                string locationId = Program.ByteArrayToString(message, position, receiveBox.Length);

                if (m_Folders.Contains(locationId))
                    Location = m_Folders[locationId] + Location;
                else
                    Location = Location + " (未知ID：" + locationId + ")";
            }
        }

        private bool SetException(Exception e)
        {
            if (this.Exception == null)
            {
                Exception = e;
                return true;
            }
            else
                return false;
        }

        /// <summary>
        /// 判断message从index开始，是不是与pattern匹配。
        /// </summary>
        /// <param name="message"></param>
        /// <param name="index"></param>
        /// <param name="pattern"></param>
        /// <returns></returns>
        private static bool Match(byte[] message, int index, byte[] pattern)
        {
            for (int i = 0; i < pattern.Length; i++)
                if (message[index + i] != pattern[i])
                    return false;
            return true;
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        /// <param name="position"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        private static DateTime GetTime(byte[] message, int position)
        {
            int year = message[position + 1] * 16 * 16 + message[position];
            position += 4;

            int month = message[position];
            position += 4;

            int day = message[position];
            position += 4;

            int hour = message[position];
            position += 4;

            int minute = message[position];
            position += 4;

            int second = message[position];
            position += 12;

            return new DateTime(year, month, day, hour, minute, second);
        }
    }
}